﻿using System;
using System.Net.Sockets;
using System.Text;
using System.IO;

public class SocketClient
{
    TcpClient tcpClient;
    NetworkStream stream;
    MemoryStream mem = new MemoryStream();

    byte[] buffer;
    int BuffseSize = 8192;

    public SocketClient(TcpClient client)
    {
        tcpClient = client;

        Console.WriteLine("连接服务器 -> " + client.Client.RemoteEndPoint);
        stream = client.GetStream();

        buffer = new byte[8192];
        stream.BeginRead(buffer, 0, buffer.Length, ReadAsync, null);
    }

    //异步读取的回调
    void ReadAsync(IAsyncResult result)
    {
        try
        {
            int readCount = stream.EndRead(result);
            if (readCount == 0) throw new Exception("读取到0字节");

            OnReceive(buffer, readCount);

            lock (stream) //再次开启读取
            {
                Array.Clear(buffer, 0, buffer.Length);
                stream.BeginRead(buffer, 0, BuffseSize, ReadAsync, null);
            }
        }
        catch (Exception e)
        {
            Console.WriteLine(e.Message);
            OnClose();
        }
    }

    void OnClose()
    {
        ServerManager.Instance().RemoveClient(tcpClient.Client.RemoteEndPoint.ToString());
        stream.Close();
        tcpClient.Close();

    }

    //解密消息体（解析长度，避免半包和粘包）
    void OnReceive(byte[] bytes, int count)
    {
        mem.Seek(0, SeekOrigin.End);
        mem.Write(bytes, 0, count);
        mem.Seek(0, SeekOrigin.Begin);

        while (RemainingBytes() > 4)
        {
            byte[] head = new byte[4];
            mem.Read(head, 0, 4);
            int length = BitConverter.ToInt32(head, 0);

            if (RemainingBytes() >= length)
            {
                byte[] content = new byte[length];
                mem.Read(content, 0, length);

                OnMessage(content);
            }
            else
            {
                //mem.Seek(-4, SeekOrigin.Current);
                mem.Position = mem.Position - 4;
                break;
            }
        }

        //把剩余的写到mem的开头
        byte[] remain = new byte[mem.Length - mem.Position];
        mem.Read(remain, 0, remain.Length);
        mem.SetLength(0);
        mem.Write(remain, 0, remain.Length);
    }
    long RemainingBytes()
    {
        return mem.Length - mem.Position;
    }

    //发送消息（自动在头部添加长度）
    void Send(byte[] bytes)
    {
        //把长度转为byte
        int length = bytes.Length;
        byte[] head = BitConverter.GetBytes(length);

        //拼接最后的byte数组
        MemoryStream mem = new MemoryStream();
        mem.Write(head, 0, head.Length);
        mem.Write(bytes, 0, bytes.Length);

        //发送最终内容
        byte[] result = mem.ToArray();
        stream.Write(result, 0, result.Length);
        mem.Close();
    }


    //---------------------------------------------------------
    //接收一条消息
    void OnMessage(byte[] bytes)
    {
        ByteBuffer buffer = new ByteBuffer(bytes);
        int protocol = buffer.ReadInt();
        string msg = buffer.ReadStringOnly();

        Console.WriteLine("一级协议" + protocol + "消息体：" + msg);
        //ServerManager.players.Add(ServerManager.Instance().dic, BitConverter.ToString(bytes));
        ServerManager.Instance().OnMessage(tcpClient, protocol, msg);
    }

    ////发送消息到服务器
    //public void SendMessage(string msg)
    //{
    //    Send(Encoding.UTF8.GetBytes(msg));
    //    Console.WriteLine("发送消息 -> " + msg);
    //}

    //发送消息+协议
    public void SendMessage(int protocol, string msg)
    {
        byte[] first = BitConverter.GetBytes(protocol);
        byte[] content = Encoding.UTF8.GetBytes(msg);

        MemoryStream mem = new MemoryStream();
        mem.Write(first, 0, first.Length);
        mem.Write(content, 0, content.Length);

        Send(mem.ToArray());
        mem.Close();

        Console.WriteLine("发送消息 -> " + msg);
    }
}